﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VoiceAI.Diagnostics;

namespace VoiceAI
{
    public class VoiceAIManager
    {
        public VoiceAIManager()
        {
            history.CollectionChanged += History_CollectionChanged;
        }
        public event NotifyCollectionChangedEventHandler HistoryChanged;
        private void History_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            HistoryChanged?.Invoke(sender, e);
        }

        private readonly List<IVoiceAI> voiceAICollection = new List<IVoiceAI>();
        public IReadOnlyCollection<IVoiceAI> VoiceAICollection => voiceAICollection;
        private readonly ObservableCollection<IResponseData> history = new ObservableCollection<IResponseData>();
        public IReadOnlyList<IResponseData> History 
        {
            get
            {
                lock (responseHistoryLocker)
                {
                    return history.ToArray();
                }
            }
        }
        public void ClearHistory()
        {
            lock (responseHistoryLocker)
            {
                history.Clear();
            }
        }
        private object voiceAICollectionLocker=new object();
        public void RegisterVoiceAI(IVoiceAI voiceAI)
        {
            lock (voiceAICollectionLocker)
            {
                if (!voiceAICollection.Contains(voiceAI))
                {
                    voiceAI.ResponseReceived += VoiceAI_ResponseReceived;
                    voiceAICollection.Add(voiceAI);
                }
            }
        }
        public void UnregisterVoiceAI(IVoiceAI voiceAI)
        {
            lock (voiceAICollectionLocker)
            {
                if (voiceAICollection.Contains(voiceAI))
                {
                    voiceAI.ResponseReceived -= VoiceAI_ResponseReceived;
                    voiceAICollection.Remove(voiceAI);
                }
            }
        }
        private object responseHistoryLocker = new object();
        private object responseActionLocker = new object();
        private void VoiceAI_ResponseReceived(IResponseData responseData)
        {
            Debug.WriteLine($"VoiceAI_ResponseReceived  {responseData.RequestText}");
            Task.Run(()=> {
                Debug.WriteLine("VoiceAI_ResponseReceived enter task");
                lock (responseActionLocker)
                {
                    if (responseActionMap.ContainsKey(responseData.ResponseType))
                    {
                        responseActionMap[responseData.ResponseType]?.Invoke(responseData);
                    }
                    else
                    {
                        defaultResponseAction?.Invoke(responseData);
                    }
                }
                if (responseData.RestoreInHistory)
                {
                    ResponseReceived?.Invoke(responseData);
                    lock (responseHistoryLocker)
                    {
                        history.Add(responseData);
                    }
                }
            });

        }

        public event Action<IResponseData> ResponseReceived;

        private readonly Dictionary<ResponseType, Action<IResponseData>>
            responseActionMap = new Dictionary<ResponseType, Action<IResponseData>>();
        private Action<IResponseData> defaultResponseAction;
        public void RegisterResponseAction(ResponseType responseType, Action<IResponseData> action)
        {
            lock (responseActionLocker)
            {
                if (responseType != ResponseType.Default)
                {
                    responseActionMap[responseType] = action;
                }
                else
                {
                    defaultResponseAction = action;
                }
            }
        }
        public void RegisterDefaultResponseAction(Action<IResponseData> action)
        {
            defaultResponseAction = action;
        }
    }
}
